const fs = require('fs').promises;
const path = require('path');
const logger = require('./logger');

/**
 * 数据存储工具
 * 用于处理JSON文件的读写操作
 */
class DataStore {
  /**
   * 创建数据存储实例
   * @param {string} filePath - 数据文件路径
   */
  constructor(filePath) {
    this.filePath = filePath;
    this.data = null;
    this.initialized = false;
  }

  /**
   * 初始化数据存储
   * 读取数据文件，如果文件不存在则创建
   */
  async init() {
    try {
      // 确保目录存在
      const dir = path.dirname(this.filePath);
      await fs.mkdir(dir, { recursive: true });

      try {
        // 尝试读取文件
        const fileContent = await fs.readFile(this.filePath, 'utf8');
        this.data = JSON.parse(fileContent);
      } catch (error) {
        if (error.code === 'ENOENT') {
          // 文件不存在，创建空数据
          this.data = [];
          await this.save();
          logger.info(`创建新数据文件: ${this.filePath}`);
        } else if (error instanceof SyntaxError) {
          // JSON解析错误
          logger.error(`数据文件格式错误: ${this.filePath}`);
          // 创建备份并重置数据
          const backupPath = `${this.filePath}.${Date.now()}.bak`;
          await fs.copyFile(this.filePath, backupPath);
          logger.info(`已创建损坏文件备份: ${backupPath}`);
          this.data = [];
          await this.save();
        } else {
          throw error;
        }
      }

      this.initialized = true;
      logger.info(`数据存储初始化成功: ${this.filePath}`);
    } catch (error) {
      logger.error(`数据存储初始化失败: ${error.message}`);
      throw error;
    }
  }

  /**
   * 确保数据存储已初始化
   */
  async ensureInitialized() {
    if (!this.initialized) {
      await this.init();
    }
  }

  /**
   * 保存数据到文件
   */
  async save() {
    try {
      await fs.writeFile(this.filePath, JSON.stringify(this.data, null, 2), 'utf8');
      logger.debug(`数据已保存到: ${this.filePath}`);
      return true;
    } catch (error) {
      logger.error(`保存数据失败: ${error.message}`);
      throw error;
    }
  }

  /**
   * 获取所有数据
   * @returns {Array} 数据数组
   */
  async getAll() {
    await this.ensureInitialized();
    return [...this.data];
  }

  /**
   * 根据ID获取单个项目
   * @param {string} id - 项目ID
   * @returns {Object|null} 找到的项目或null
   */
  async getById(id) {
    await this.ensureInitialized();
    return this.data.find(item => item.id === id) || null;
  }

  /**
   * 添加新项目
   * @param {Object} item - 要添加的项目
   * @returns {Object} 添加的项目
   */
  async add(item) {
    await this.ensureInitialized();
    
    // 确保项目有ID
    if (!item.id) {
      item.id = this.generateId();
    }
    
    // 添加时间戳
    if (!item.createdAt) {
      item.createdAt = new Date().toISOString();
    }
    item.updatedAt = new Date().toISOString();
    
    this.data.push(item);
    await this.save();
    return item;
  }

  /**
   * 更新项目
   * @param {string} id - 项目ID
   * @param {Object} updates - 更新内容
   * @returns {Object|null} 更新后的项目或null
   */
  async update(id, updates) {
    await this.ensureInitialized();
    
    const index = this.data.findIndex(item => item.id === id);
    if (index === -1) {
      return null;
    }
    
    // 更新时间戳
    updates.updatedAt = new Date().toISOString();
    
    // 合并更新
    this.data[index] = { ...this.data[index], ...updates };
    await this.save();
    return this.data[index];
  }

  /**
   * 删除项目
   * @param {string} id - 项目ID
   * @returns {boolean} 是否成功删除
   */
  async delete(id) {
    await this.ensureInitialized();
    
    const initialLength = this.data.length;
    this.data = this.data.filter(item => item.id !== id);
    
    if (this.data.length !== initialLength) {
      await this.save();
      return true;
    }
    return false;
  }

  /**
   * 查询数据
   * @param {Function} predicate - 过滤函数
   * @returns {Array} 匹配的项目数组
   */
  async query(predicate) {
    await this.ensureInitialized();
    return this.data.filter(predicate);
  }

  /**
   * 生成唯一ID
   * @returns {string} 唯一ID
   */
  generateId() {
    return Date.now().toString(36) + Math.random().toString(36).substr(2, 5);
  }

  /**
   * 清空所有数据
   * 主要用于测试
   */
  async clear() {
    await this.ensureInitialized();
    this.data = [];
    await this.save();
  }
}

module.exports = DataStore;